package com.company.game00;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import static com.company.game00.MyUtil.*;


public class MyFrame extends Frame implements Runnable {

    private Tank heroTank;
    private List<EnemyTank> enemyTanks = Collections.synchronizedList(new LinkedList<>());
    private List<Boom> booms = new LinkedList<>();

    public MyFrame() {
        initFrame();
        initEventListener();
        ThreadUtil.execute(this);
    }

    public static int TOP = 0;

    private void initFrame() {
        setSize(FRAME_WIDTH, FRAME_HEIGHT);
        setTitle("坦克大战");
        setLocation(SCREEN_WIDTH - FRAME_WIDTH >> 1, SCREEN_HEIGHT - FRAME_HEIGHT >> 1);
        setResizable(false);
        setVisible(true);
        TOP = getInsets().top;
    }

    private void initEventListener() {
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                switch (game_state) {
                    case GAME_STATE_MENU:
                        switch (e.getKeyCode()) {
                            case KeyEvent.VK_UP:
                            case KeyEvent.VK_W:
                                if (menu_index > 0) menu_index--;
                                break;
                            case KeyEvent.VK_DOWN:
                            case KeyEvent.VK_S:
                                if (menu_index < 4) menu_index++;
                                break;
                            case KeyEvent.VK_ENTER:
                            case KeyEvent.VK_SPACE:
                                game_state = menu_index + 1;
                                newGame();
                                new Audio("/static/start.wav").play();
                                break;
                        }
                        break;
                    case GAME_STATE_RUN:
                        switch (e.getKeyCode()) {
                            case KeyEvent.VK_UP:
                            case KeyEvent.VK_W:
                                heroTank.setDir(Tank.DIR_UP);
                                heroTank.setState(Tank.STATE_MOVE);
                                break;
                            case KeyEvent.VK_DOWN:
                            case KeyEvent.VK_S:
                                heroTank.setDir(Tank.DIR_DOWN);
                                heroTank.setState(Tank.STATE_MOVE);
                                break;
                            case KeyEvent.VK_LEFT:
                            case KeyEvent.VK_A:
                                heroTank.setDir(Tank.DIR_LEFT);
                                heroTank.setState(Tank.STATE_MOVE);
                                break;
                            case KeyEvent.VK_RIGHT:
                            case KeyEvent.VK_D:
                                heroTank.setDir(Tank.DIR_RIGHT);
                                heroTank.setState(Tank.STATE_MOVE);
                                break;
                        }
                        break;
                }
            }

            @Override // 按键松开
            public void keyReleased(KeyEvent e) {
                if (game_state == GAME_STATE_RUN) {
                    switch (e.getKeyCode()) {
                        case KeyEvent.VK_W:
                        case KeyEvent.VK_S:
                        case KeyEvent.VK_A:
                        case KeyEvent.VK_D:
                        case KeyEvent.VK_UP:
                        case KeyEvent.VK_DOWN:
                        case KeyEvent.VK_LEFT:
                        case KeyEvent.VK_RIGHT:
                            heroTank.setState(Tank.STATE_STAND);
                            break;
                        case KeyEvent.VK_J:
                        case KeyEvent.VK_X:
                            heroTank.fire();
                            break;
                    }
                }
            }
        });
    }

    int enemyCount;

    private void newGame() {
        heroTank = new Tank(400, 300, Tank.DIR_UP);
        ThreadUtil.execute(() -> {
            for (int i = 0; i < 4; i++) {
                ThreadUtil.sleep(ENEMY_BORN_INTERVAL);
                int x = RandomUtil.randomInt(Tank.RADIUS, FRAME_WIDTH - Tank.RADIUS);
                int y = TOP + Tank.RADIUS;
                EnemyTank enemyTank = new EnemyTank(x, y, Tank.DIR_DOWN);
                enemyTanks.add(enemyTank);
                enemyCount++;
            }
            ThreadUtil.sleep(5000);
            while (true) {
                if (enemyTanks.size() < 4 && enemyCount < ENEMY_MAX_COUNT) {
                    ThreadUtil.sleep(ENEMY_BORN_INTERVAL);
                    int x = RandomUtil.randomInt(Tank.RADIUS, FRAME_WIDTH - Tank.RADIUS);
                    int y = TOP + Tank.RADIUS;
                    EnemyTank tank = new EnemyTank(x, y, Tank.DIR_DOWN);
                    enemyTanks.add(tank);
                    enemyCount++;
                }
            }
        });
    }

    @Override
    public void update(Graphics g) {
        switch (game_state) {
            case GAME_STATE_MENU:
                drawMenu(g);
                break;
            case GAME_STATE_RUN:
                drawRun(g);
                break;
        }
    }

    private void drawRun(Graphics g) {
        g.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
        if (heroTank.isVisible()) heroTank.draw(g);
        for (int i = 0; i < enemyTanks.size(); i++) {
            EnemyTank enemyTank = enemyTanks.get(i);
            if (enemyTank.isVisible()) {
                enemyTank.draw(g); // 绘制敌方坦克
                // 判断是否击中我方坦克
                if (heroTank.isVisible()) {
                    for (int j = 0; j < enemyTank.getBullets().size(); j++) {
                        Bullet bullet = enemyTank.getBullets().get(j);
                        boolean hit = isHit(bullet, heroTank);
                        if (hit) {
                            booms.add(new Boom(heroTank.getX() - Tank.RADIUS, heroTank.getY() - Tank.RADIUS));
                        }
                    }
                }
            } else {
                enemyTanks.remove(enemyTank);
            }
        }
        for (int i = 0; i < heroTank.getBullets().size(); i++) {
            Bullet bullet = heroTank.getBullets().get(i);
            for (int j = 0; j < enemyTanks.size(); j++) {
                EnemyTank enemyTank = enemyTanks.get(j);
                if (!heroTank.isVisible()) return;
                boolean hit = isHit(bullet, enemyTank);
                if (hit) {
                    booms.add(new Boom(enemyTank.getX() - Tank.RADIUS, enemyTank.getY() - Tank.RADIUS));
                }
            }
        }

        for (Boom boom : booms) {
            if (boom.getLife() == 15) {
                booms.remove(boom);
                return;
            }
            boom.draw(g);
        }

    }

    int menu_index;
    int game_state;

    private void drawMenu(Graphics g) {
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);

        int x = FRAME_WIDTH - 50 >> 1; // menu_x = (frame_with - font_with) / 2
        int y = FRAME_HEIGHT / 3;
        int dis = 30;
        g.setColor(Color.WHITE);
        String[] menus = {"开始游戏", "继续游戏", "游戏帮助", "关于游戏", "退出游戏"};
        for (int i = 0; i < menus.length; i++) {
            if (menu_index == i) g.setColor(Color.RED);
            else g.setColor(Color.WHITE);
            g.drawString(menus[i], x, y + (dis * i));
        }
    }

    @Override
    public void run() { // 界面重绘线程
        while (true) {
            repaint();
            ThreadUtil.sleep(30);
        }
    }

    public boolean isHit(Bullet bullet, Tank tank) {
        boolean touch = MyUtil.isTouch(tank.getX(), tank.getY(), Tank.RADIUS, bullet.getX(), bullet.getY());
        if (touch) {
            bullet.setVisible(false);
            int hp = tank.getHp() - bullet.getAtk();
            if (hp > 0) tank.setHp(hp);
            else tank.setVisible(false);

        }
        return touch;
    }
}
